package com.aspire.nm.component.cmppserver.handler;


import java.net.InetSocketAddress;
import java.util.Hashtable;
import java.util.TimerTask;

import javax.annotation.Resource;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.springframework.stereotype.Service;

import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppConnectPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppConnectRespPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppDeliverRespPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppSubmitPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppSubmitRespPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppTerminatePacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppTerminateRespPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.Version;
import com.aspire.nm.component.cmppserver.runTime.SysRunTimeService;
import com.aspire.nm.component.cmppserver.util.InvokeRateUtil;
import com.aspire.nm.component.cmppserver.util.LogService;
import com.aspire.nm.component.cmppserver.util.MessageIdGenerator;
import com.aspire.nm.component.cmppserver.validate.CmppConnectAuthenticator;
import com.aspire.nm.component.cmppserver.validate.CmppSubmitPacketCheck;
import com.aspire.nm.component.commonUtil.secret.secret.SecretUtil;
@Service
public class EventHandler extends IoHandlerAdapter {
	
	
	@Resource
	private LogService logService;
	@Resource
	private SysRunTimeService sysRunTimeService;
	@Resource
	private CmppConnectAuthenticator cmppConnectAuthenticator;
	@Resource
	private CmppSubmitPacketCheck cmppSubmitPacketCheck;
	
	@Resource
	private ProcessSubmitManager processSubmitManager;
	
    public void messageReceived(IoSession session, Object message) throws Exception {
    	if(message instanceof CmppConnectPacket){
    		CmppPacket resp = processCmppConnectPacket(session, (CmppConnectPacket) message);
    		session.write(resp);
    	}
    	if(message instanceof CmppSubmitPacket){
    	    
    	    InvokeRateUtil.invokeRate_receive_submit.count();
    	    
    		CmppSubmitPacket req = (CmppSubmitPacket)message;
    		logService.submit(session, req);
    		CmppSubmitRespPacket resp = receivedCmppSubmitPacket(session, req);
    		
    		if(resp.getResult() == CmppSubmitRespPacket.RESULT_OK){
    		    resp.setResult(processSubmitManager.process(session, req,resp));
    		}
    		session.write(resp);
    		
    		InvokeRateUtil.invokeRate_send_submitresp.count();
    		
			logService.submitResp(session, resp);
    	}
    	
    	
    	
    	if(message instanceof CmppDeliverRespPacket){
    	    InvokeRateUtil.invokeRate_receive_deliverresp.count();
    		logService.deliverResp(session, (CmppDeliverRespPacket) message);
    		receivedCmppDeliverRespPacket(session , (CmppDeliverRespPacket)message);
    	}
    	if(message instanceof CmppTerminatePacket){
    		logService.terminate(session, (CmppTerminatePacket)message);
    		CmppPacket resp = receivedCmppTerminatePacket(session, (CmppTerminatePacket) message);
    		logService.terminateResp(session, (CmppTerminateRespPacket)resp);
    		session.write(resp);
    	}
    	if(message instanceof CmppTerminateRespPacket){
    		logService.terminateResp(session, (CmppTerminateRespPacket)message);
    		receivedCmppTerminateRespPacket(session, (CmppTerminateRespPacket) message);
    	}
    }
    
    
    
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
    	logService.throwAble(session, cause);
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    private CmppPacket processCmppConnectPacket(IoSession session, CmppConnectPacket cmppConnectPacket){
    	
    	int stat = cmppConnectAuthenticator.auth(cmppConnectPacket.getSourceAddr(), cmppConnectPacket.getAuthenticatorSource(),
				((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress(),cmppConnectPacket.getTimestamp());
		byte[] authenticatorISMG = new byte[16];
    	if(stat == CmppConnectRespPacket.STATUS_SUCCESS){
    		String authISMG = stat + new String(cmppConnectPacket.getAuthenticatorSource()) + sysRunTimeService.getClientConfig(cmppConnectPacket.getSourceAddr()).getPass();
    		authenticatorISMG = SecretUtil.ToMd5(authISMG.getBytes());
    	}
    	CmppConnectRespPacket cmppConnectRespPacket = new CmppConnectRespPacket(cmppConnectPacket.getVersion());
    	cmppConnectRespPacket.setSequenceId(cmppConnectPacket.getSequenceId());
    	cmppConnectRespPacket.setStatus(stat);
    	cmppConnectRespPacket.setAuthenticatorISMG(authenticatorISMG);
    	cmppConnectRespPacket.bizParams = cmppConnectPacket;
		return cmppConnectRespPacket;
    	 
    }
    
    
    private CmppSubmitRespPacket receivedCmppSubmitPacket(IoSession session, CmppSubmitPacket cmppSubmitPacket) {
    	
    	Version version = sysRunTimeService.getUserRunTime(session).getConnection(session).getVersion();
    	
    	int len = cmppSubmitPacket.getDestTerminalId().length;
    	long msgId = MessageIdGenerator.getMessageIdGenerator().getMsgId((short) len);
    	
    	int status = cmppSubmitPacketCheck.check(cmppSubmitPacket,session,version);
    	
//    	byte registeredDelivery = cmppSubmitPacket.getRegisteredDelivery();
//		cmppSubmitPacket.setRegisteredDelivery(registeredDelivery);
		
		
		CmppSubmitRespPacket resp = new CmppSubmitRespPacket(version);
		resp.setSequenceId(cmppSubmitPacket.getSequenceId());
		resp.setMsgId(msgId);
		resp.setResult(status);
		
		return resp;
    }
    
    
    
    private void receivedCmppDeliverRespPacket(IoSession session, CmppDeliverRespPacket cmppDeliverRespPacket) {
    	Hashtable<Integer, TimerTask> deliverRetryHt  = sysRunTimeService.getUserRunTime(session).getConnection(session).getMoSender().getDeliveryRetryHt();
    	if(deliverRetryHt != null){
    	    TimerTask task = deliverRetryHt.remove(cmppDeliverRespPacket.getSequenceId());
            if(task != null){
                task.cancel();
                sysRunTimeService.getUserRunTime(session).getConnection(session).getMoSender().getTimer().purge();
//              CmppDeliverPacket cmppDeliverPacket  = ((MORetryTask)task).getPk();
                //ToDo
            }else{
                //消息经重试后过期
            }
    	}
    }
    
    
    private CmppPacket receivedCmppTerminatePacket(IoSession session, CmppTerminatePacket cmppTerminatePacket){
    	CmppTerminateRespPacket resp = new CmppTerminateRespPacket();
		resp.setSequenceId(cmppTerminatePacket.getSequenceId());
		return resp;
    }
    private void receivedCmppTerminateRespPacket(IoSession session, CmppTerminateRespPacket cmppTerminateRespPacket) {
    	
	}
    
    
    
    
    
}
